package com.ipartek.formacion.gestformwww.modelo.clases;

import com.ipartek.formacion.gestformwww.modelo.beans.DiaClase;
import com.ipartek.formacion.gestformwww.modelo.beans.excepciones.GestorFormacionExcepcion;
import com.ipartek.formacion.gestformwww.modelo.interfaces.IDiaClaseDAO;
import com.ipartek.formacion.gestformwww.controlador.Verificador;
import com.ipartek.formacion.gestformwww.modelo.beans.Calendario;
import com.ipartek.formacion.gestformwww.modelo.beans.Curso;
import java.sql.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Alvaro y Karmele
 */
public class SQLServerDiaClaseDAO implements IDiaClaseDAO {

    private static ResourceBundle rb;

    public SQLServerDiaClaseDAO() {
        rb = ResourceBundle.getBundle("com.ipartek.formacion.gestformwww.controlador.excepciones");
    }

    private DiaClase instanciarDiaClase(ResultSet rs) throws SQLException {

        DiaClase diaclase = new DiaClase();
        diaclase.setModId(rs.getInt("ModId"));
        diaclase.setClaId(rs.getInt("ClaId"));
        diaclase.setDocId(rs.getInt("DocId"));
        diaclase.setCurId(rs.getInt("CurId"));
        diaclase.setClaFecha(rs.getTimestamp("ClaFecha"));
        diaclase.setClaHoraInicioMan(rs.getString("ClaHoraInicioMañ"));
        diaclase.setClaHoraFinMan(rs.getString("ClaHoraFinMañ"));
        diaclase.setClaObserv(rs.getString("ClaObserv"));
        diaclase.setClaHoraInicioTar(rs.getString("ClaHoraInicioTar"));
        diaclase.setClaHoraFinTar(rs.getString("ClaHoraFinTar"));
        diaclase.setAulId(rs.getInt("AulId"));

        return diaclase;
    }

    /**
     * Método que lista los dias de clase.
     * @author
     * @param idCurso, Fecha
     * @return  devuelve un Array List con los días de clase
     */
    public ArrayList<DiaClase> listarDiasClase(Integer idcurso, Calendar fecha) throws GestorFormacionExcepcion {
        ArrayList<DiaClase> diaclase = new ArrayList<DiaClase>();
        DiaClase diacla = null;
        Connection conexion = null;
        PreparedStatement stmt=null;
        ResultSet rs=null;
        Calendar fechafin = Calendar.getInstance();
        Calendar fechaini = Calendar.getInstance();
        Calendar cal = (Calendar) fecha.clone();
        fechaini.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 0);
        fechafin.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH));
        try {
            conexion = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }

        try {
            stmt = conexion.prepareStatement("SELECT c.ModId, m.ModDescr, c.ClaId, c.DocId, d.DocNom, c.CurId, c.ClaFecha, c.ClaHoraInicioMañ, c.ClaHoraFinMañ, c.ClaObserv, c.ClaHoraInicioTar, c.ClaHoraFinTar, c.AulId, a.AulNom  FROM (((CLASE AS c LEFT OUTER JOIN DOCENTE AS d ON c.DocId=d.DocId) LEFT OUTER JOIN AULA AS a ON c.AulId=a.AulId) LEFT OUTER JOIN MODULO AS m ON c.ModId=m.ModId) WHERE c.CurId=? AND c.ClaFecha BETWEEN ? AND ? ORDER BY c.ClaFecha");
            stmt.setInt(1, idcurso);
            stmt.setTimestamp(2, new Timestamp(fechaini.getTimeInMillis()));
            stmt.setTimestamp(3, new Timestamp(fechafin.getTimeInMillis()));
            rs = stmt.executeQuery();
            while (rs.next()) {
                diacla = instanciarDiaClase(rs);
                diacla.setModNom(rs.getString("ModDescr"));
                diacla.setDocNom(rs.getString("DocNom"));
                diacla.setAulNom(rs.getString("AulNom"));
                conflicto(conexion, diacla);
                diaclase.add(diacla);
            }

        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            try {
                stmt.close();
                rs.close();
                SQLServerDAOFactory.desconecta(conexion);
            } catch (SQLException ex) {
                Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        return diaclase;
    }
    /**
     * Metodo que calcula los dias de clase de todo el curso
     */
    public ArrayList<DiaClase> listarDiasClaseCurso(Curso curso, Calendar fecha) throws GestorFormacionExcepcion {
        ArrayList<DiaClase> diaclase = new ArrayList<DiaClase>();
        DiaClase diacla = null;
        Connection conexion = null;
        PreparedStatement stmt=null;
        ResultSet rs=null;
        int idCurso = curso.getCurId();
        Timestamp fechaIni = curso.getCurFchaInReal();
        Timestamp fechaFin = curso.getCurFchaFinReal();
//        Calendar fechafin = Calendar.getInstance();
//        Calendar fechaini = Calendar.getInstance();
        Calendar cal = (Calendar) fecha.clone();
//        fechaini.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 0);
//        fechafin.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH));
        try {
            conexion = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }

        try {
            stmt = conexion.prepareStatement("SELECT c.ModId, m.ModDescr, c.ClaId, c.DocId, d.DocNom, c.CurId, c.ClaFecha, c.ClaHoraInicioMañ, c.ClaHoraFinMañ, c.ClaObserv, c.ClaHoraInicioTar, c.ClaHoraFinTar, c.AulId, a.AulNom  FROM (((CLASE AS c LEFT OUTER JOIN DOCENTE AS d ON c.DocId=d.DocId) LEFT OUTER JOIN AULA AS a ON c.AulId=a.AulId) LEFT OUTER JOIN MODULO AS m ON c.ModId=m.ModId) WHERE c.CurId=? AND c.ClaFecha BETWEEN ? AND ? ORDER BY c.ClaFecha");
            stmt.setInt(1, idCurso);
            stmt.setTimestamp(2,fechaIni);
            stmt.setTimestamp(3, fechaFin);
            rs = stmt.executeQuery();
            while (rs.next()) {
                diacla = instanciarDiaClase(rs);
                diacla.setModNom(rs.getString("ModDescr"));
                diacla.setDocNom(rs.getString("DocNom"));
                diacla.setAulNom(rs.getString("AulNom"));
                conflicto(conexion, diacla);
                diaclase.add(diacla);
            }

        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            try {
                stmt.close();
                rs.close();
                SQLServerDAOFactory.desconecta(conexion);
            } catch (SQLException ex) {
                Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        return diaclase;
    }

    /**
     * Método que calcula la duracion de los dias de clase de un curso.
     * @author
     * @param idCurso
     * @return  devuelve un entero con el numero de días de duración
     */
    private void conflicto(Connection conexion, DiaClase dia) throws SQLException {
        ResultSet rs = null;
        PreparedStatement stmt = conexion.prepareStatement("SELECT C1.ClaId, C1.ClaHoraInicioMañ, C1.ClaHoraFinMañ, C1.ClaHoraInicioTar, C1.ClaHoraFinTar, C1.AulId, C1.DocId FROM Clase AS C1, Clase AS C2 WHERE C2.ClaId = ? AND C1.ClaId<>C2.ClaId AND (C1.AulId=C2.AulId OR C1.DocId=C2.DocId) AND C1.ClaFecha = C2.ClaFecha");
        stmt.setInt(1, dia.getClaId());
        rs = stmt.executeQuery();
        while (rs.next()) {
            if (Verificador.comprobarIntervaloHoras(dia.getClaHoraInicioMan(), dia.getClaHoraFinMan(), rs.getString("ClaHoraInicioMañ"), rs.getString("ClaHoraFinMañ"))) {
                if (dia.getAulId() == rs.getInt("AulId")) {
                    dia.setConflictoAula(true);
                }
                if (dia.getDocId() == rs.getInt("DocId")) {
                    dia.setConflictoDocente(true);
                }
            }
            if (Verificador.comprobarIntervaloHoras(dia.getClaHoraInicioTar(), dia.getClaHoraFinTar(), rs.getString("ClaHoraInicioTar"), rs.getString("ClaHoraFinTar"))) {
                if (dia.getAulId() == rs.getInt("AulId")) {
                    dia.setConflictoAula(true);
                }
                if (dia.getDocId() == rs.getInt("DocId")) {
                    dia.setConflictoDocente(true);
                }
            }
        }
//        rs.close();
//        stmt.close();
//        SQLServerDAOFactory.desconecta(conexion);
    }

    public int duracionDiasClase(Integer idcurso) throws GestorFormacionExcepcion {
        DiaClase diacla = null;
        Connection conexion = null;
        int minutostotales = 0;

        try {
            conexion = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }

        try {
            PreparedStatement stmt = conexion.prepareStatement("SELECT * FROM Clase WHERE CurId=" + idcurso);
            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                diacla = instanciarDiaClase(rs);
                //Convertir a fecha
                if (diacla.getClaHoraFinMan() != null && !diacla.getClaHoraFinMan().isEmpty() && diacla.getClaHoraInicioMan() != null && !diacla.getClaHoraInicioMan().isEmpty()) {
                    minutostotales += Verificador.convertirHoraAMinutos(diacla.getClaHoraFinMan()) - Verificador.convertirHoraAMinutos(diacla.getClaHoraInicioMan());
                }
                if (diacla.getClaHoraFinTar() != null && !diacla.getClaHoraFinTar().isEmpty() && diacla.getClaHoraInicioTar() != null && !diacla.getClaHoraInicioTar().isEmpty()) {
                    minutostotales += Verificador.convertirHoraAMinutos(diacla.getClaHoraFinTar()) - Verificador.convertirHoraAMinutos(diacla.getClaHoraInicioTar());
                }
            }
            stmt.close();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(conexion);
        }

        return minutostotales;
    }

    /**
     * Método que crea el calendario del curso.
     * @author
     * @param calendario
     */
    public void crearCalendario(Calendario calendario) throws GestorFormacionExcepcion {
        Connection con = null;
        SentenciaNula stmt = null;
        DiaClase d = calendario.getDiaClase();
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            //calendario.getCalFechaFin().setTime(calendario.getCalFechaFin().getTime() + 86400000);
            stmt = new SentenciaNula(con, "INSERT INTO CLASE (ModId, DocId, CurId, ClaFecha, ClaHoraInicioMañ, ClaHoraFinMañ, ClaObserv, ClaHoraInicioTar, ClaHoraFinTar, AulId) VALUES(?,?,?,?,?,?,?,?,?,?)");
            Calendar c = Calendar.getInstance();
            Calendar fin = Calendar.getInstance();
            c.setTime(calendario.getCalFechaIni());
            fin.setTime(calendario.getCalFechaFin());
            for (; c.before(fin) || c.equals(fin); c.add(Calendar.DAY_OF_YEAR, 1)) {
                if (c.get(c.DAY_OF_WEEK) != Calendar.SUNDAY && (c.get(c.DAY_OF_WEEK) != Calendar.SATURDAY || calendario.isSabados())) {
                    stmt.setInt(1, d.getModId());
                    stmt.setInt(2, d.getDocId());
                    stmt.setInt(3, d.getCurId());
                    stmt.setTimestamp(4, new Timestamp(c.getTimeInMillis()));
                    stmt.setString(5, d.getClaHoraInicioMan());
                    stmt.setString(6, d.getClaHoraFinMan());
                    stmt.setString(7, d.getClaObserv());
                    stmt.setString(8, d.getClaHoraInicioTar());
                    stmt.setString(9, d.getClaHoraFinTar());
                    stmt.setInt(10, d.getAulId());
                    stmt.executeUpdate();
                }
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            try {
                stmt.close();
            } catch (SQLException ex) {
                Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            }
            SQLServerDAOFactory.desconecta(con);
        }
        comprobarConflictos(getListaFechas(calendario));
    }

    /**
     * Devuelve true si ya existe algún día de clase entre el rango de fechas indicado
     * @param c Calendario con fecha inicio y fecha fin
     * @return
     * @throws GestorFormacionExcepcion
     */
    public boolean comprobarDias(Calendario c) throws GestorFormacionExcepcion {
        Connection con = null;
        SentenciaNula stmt = null;
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        boolean existe = false;
        stmt = new SentenciaNula(con, "SELECT ClaId FROM clase WHERE CurId = ? AND ClaFecha BETWEEN ? AND ?");
        try {
            stmt.setInt(1, c.getDiaClase().getCurId());
            stmt.setTimestamp(2, c.getCalFechaIni());
            stmt.setTimestamp(3, c.getCalFechaFin());
            if (stmt.executeQuery().next()) {
                existe = true;
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }

        return existe;
    }

    /**
     * Modifica el rango de fechas de un curso
     * @author Sara y Victor
     * @param calendario: El calendario que contiene el rango de fechas y los datos que vamos a actualizar
     */
    public void modificarCalendario(Calendario calendario) throws GestorFormacionExcepcion {
        Connection con = null;
        SentenciaNula stmt = null;
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            stmt = new SentenciaNula(con, "UPDATE CLASE SET ModId =?, DocId=?, ClaHoraInicioMañ=?, ClaHoraFinMañ=?, ClaObserv=?, ClaHoraInicioTar=?, ClaHoraFinTar=?, AulId=? WHERE CurId=? AND ClaFecha BETWEEN ? AND ?");
            DiaClase d = calendario.getDiaClase();
            stmt.setInt(1, d.getModId());
            stmt.setInt(2, d.getDocId());
            stmt.setString(3, d.getClaHoraInicioMan());
            stmt.setString(4, d.getClaHoraFinMan());
            stmt.setString(5, d.getClaObserv());
            stmt.setString(6, d.getClaHoraInicioTar());
            stmt.setString(7, d.getClaHoraFinTar());
            stmt.setInt(8, d.getAulId());
            stmt.setInt(9, d.getCurId());
            stmt.setTimestamp(10, calendario.getCalFechaIni());
            stmt.setTimestamp(11, calendario.getCalFechaFin());
            stmt.executeUpdate();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        comprobarConflictos(getListaFechas(calendario));
    }

    /**
     * Borra el calendario de un curso
     * @author Sara y Victor
     * @param idCurso El identificador del curso
     */
    public void borrarCalendario(Integer idCurso) throws GestorFormacionExcepcion {
        Connection con = null;
        SentenciaNula stmt = null;
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        ArrayList<Timestamp> fechas = getListaFechas(idCurso);
        try {
            stmt = new SentenciaNula(con, "DELETE FROM CLASE WHERE CurId=?");
            stmt.setInt(1, idCurso);
            stmt.executeUpdate();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        comprobarConflictos(fechas);
    }

    /**
     * Borra el calendario de varios curso
     * @author Sara y Victor
     * @param ArrayList<DiaClase> Array de identificadores de un curso
     */
    public void borrarDiasClase(ArrayList<Integer> idClases) throws GestorFormacionExcepcion {
        Connection con = null;
        SentenciaNula stmt = null;
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        ArrayList<Timestamp> fechas = getListaFechas(idClases);
        try {
            stmt = new SentenciaNula(con, "DELETE FROM CLASE WHERE ClaId=?");
            for (Integer x : idClases) {
                stmt.setInt(1, x);
                stmt.executeUpdate();
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        comprobarConflictos(fechas);
    }

    /**
     * Método que borra el calendario de un curso.
     * @author
     * @param Calendario
     */
    public void borrarCalendario(Calendario calendario) throws GestorFormacionExcepcion {
        Connection con = null;
        SentenciaNula stmt = null;
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        ArrayList<Timestamp> fechas = getListaFechas(calendario);
        try {

            stmt = new SentenciaNula(con, "DELETE FROM CLASE WHERE CurId=? AND ClaFecha<=? AND ClaFecha>=?");
            stmt.setInt(1, calendario.getDiaClase().getCurId());
            stmt.setTimestamp(3, calendario.getCalFechaIni());
            stmt.setTimestamp(2, calendario.getCalFechaFin());
            stmt.executeUpdate();

        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        comprobarConflictos(fechas);
    }

    /**
     * Carga la fecha del primer dia de clase del curso
     * @author Sara y Victor
     * @param idcurso: El identificador del curso
     * @return Calendar: La fecha del primer dia de clase del curso
     */
    public Calendar getPrimerDia(Integer idcurso) throws GestorFormacionExcepcion {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        Calendar cal = null;
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            stmt = con.prepareStatement("SELECT CurFchaInReal FROM curso WHERE CurId=?");
            stmt.setInt(1, idcurso);
            rs = stmt.executeQuery();
            if (rs.next()) {
                cal = Calendar.getInstance();
                cal.setTime(rs.getTimestamp("CurFchaInReal"));
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return cal;
    }

    public Calendar getUltimoDia(Integer idcurso) throws GestorFormacionExcepcion {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        Calendar cal = null;
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            stmt = con.prepareStatement("SELECT CurFchaFinReal FROM curso WHERE CurId=?");
            stmt.setInt(1, idcurso);
            rs = stmt.executeQuery();
            if (rs.next()) {
                cal = Calendar.getInstance();
                cal.setTime(rs.getTimestamp("CurFchaFinReal"));
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return cal;
    }

    /**
     * Carga un dia de clase
     * @author Sara y Victor
     * @param idClase: El identificador del dia que queremos cargar
     * @return DiaClase: El dia de clase y null si no existe
     */
    public DiaClase getDiaClase(Integer idClase) throws GestorFormacionExcepcion {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        DiaClase dia = null;
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            stmt = con.prepareStatement("SELECT ModId, ClaId, DocId, CurId, ClaFecha, ClaHoraInicioMañ, ClaHoraFinMañ, ClaObserv, ClaHoraInicioTar, ClaHoraFinTar, AulId FROM clase WHERE ClaId=?");
            stmt.setInt(1, idClase);
            rs = stmt.executeQuery();
            if (rs.next()) {
                dia = instanciarDiaClase(rs);
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        return dia;
    }

    /**
     * Método que obtiene la lista de fechas de un calendario.
     * @author
     * @param calendario
     * @return  devuelve un ArrayList de fechas.
     */
    public ArrayList<DiaClase> getDiasConflictos(DiaClase diaClase) throws GestorFormacionExcepcion {
        Connection conexion = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        ArrayList<DiaClase> dias = new ArrayList<DiaClase>();
        DiaClase dia = null;
        try {
            conexion = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            stmt = conexion.prepareStatement("SELECT CUR.CurNom, Aula.AulNom, Docente.DocNom, Docente.DocApe1, C1.ModId, C1.ClaId, C1.DocId, C1.CurId, C1.ClaFecha, C1.ClaHoraInicioMañ, C1.ClaHoraFinMañ, C1.ClaObserv, C1.ClaHoraInicioTar, C1.ClaHoraFinTar, C1.AulId FROM (((Clase AS C1 INNER JOIN Aula ON C1.AulId=Aula.AulId) INNER JOIN Docente ON C1.DocId=Docente.DocId) INNER JOIN Curso AS CUR ON C1.CurId=CUR.CurId), Clase AS C2 WHERE C2.ClaId = ? AND C1.ClaId<>C2.ClaId AND (C1.AulId=C2.AulId OR C1.DocId=C2.DocId) AND C1.ClaFecha = C2.ClaFecha ORDER BY CUR.CurNom");
            stmt.setInt(1, diaClase.getClaId());
            rs = stmt.executeQuery();
            while (rs.next()) {
                if (Verificador.comprobarIntervaloHoras(diaClase.getClaHoraInicioMan(), diaClase.getClaHoraFinMan(), rs.getString("ClaHoraInicioMañ"), rs.getString("ClaHoraFinMañ"))
                        || Verificador.comprobarIntervaloHoras(diaClase.getClaHoraInicioTar(), diaClase.getClaHoraFinTar(), rs.getString("ClaHoraInicioTar"), rs.getString("ClaHoraFinTar"))) {
                    if (diaClase.getAulId() == rs.getInt("AulId") || diaClase.getDocId() == rs.getInt("DocId")) {
                        dia = instanciarDiaClase(rs);
                        dia.setCurNom(rs.getString("CurNom"));
                        dia.setAulNom(rs.getString("AulNom"));
                        dia.setDocNom(rs.getString("DocNom"));
                        dia.setDocApe1(rs.getString("DocApe1"));
                        dias.add(dia);
                    }
                }
            }
            rs.close();
            stmt.close();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(conexion);
        }
        return dias;
    }

    private ArrayList<Timestamp> getListaFechas(Calendario calendario) throws GestorFormacionExcepcion {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        ArrayList<Timestamp> fechas = new ArrayList<Timestamp>();
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            stmt = con.prepareStatement("SELECT ClaFecha FROM clase WHERE CurId=? AND ClaFecha BETWEEN ? AND ?");
            stmt.setInt(1, calendario.getDiaClase().getCurId());
            stmt.setTimestamp(2, calendario.getCalFechaIni());
            stmt.setTimestamp(3, calendario.getCalFechaFin());
            rs = stmt.executeQuery();
            while (rs.next()) {
                fechas.add(rs.getTimestamp("ClaFecha"));
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        return fechas;
    }

    /**
     * Método que obtiene la lista de fechas de un calendario.
     * @author
     * @param ArrayList<Integer> de clases
     * @return  devuelve un ArrayList de fechas.
     */
    private ArrayList<Timestamp> getListaFechas(ArrayList<Integer> clases) throws GestorFormacionExcepcion {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        ArrayList<Timestamp> fechas = new ArrayList<Timestamp>();
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            stmt = con.prepareStatement("SELECT ClaFecha FROM clase WHERE ClaId=?");
            for (Integer id : clases) {
                stmt.setInt(1, id);
                rs = stmt.executeQuery();
                if (rs.next()) {
                    fechas.add(rs.getTimestamp("ClaFecha"));
                }
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        return fechas;
    }

    private ArrayList<Timestamp> getListaFechas(Integer idCurso) throws GestorFormacionExcepcion {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        ArrayList<Timestamp> fechas = new ArrayList<Timestamp>();
        try {
            con = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }
        try {
            stmt = con.prepareStatement("SELECT ClaFecha FROM clase WHERE CurId=?");
            stmt.setInt(1, idCurso);
            rs = stmt.executeQuery();
            while (rs.next()) {
                fechas.add(rs.getTimestamp("ClaFecha"));
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(con);
        }
        return fechas;
    }

    /**
     * Método que comprueba los conflictos de unos dias concretos.
     * @author
     * @param ArrayList de fechas.
     */
    private void comprobarConflictos(ArrayList<Timestamp> fechas) throws GestorFormacionExcepcion {
        ArrayList<DiaClase> clases = null;
        for (Timestamp dia : fechas) {
            clases = getDias(dia);
            for (DiaClase diaClase : clases) {
                actualizarObservaciones(diaClase);
            }
        }
    }

    private ArrayList<DiaClase> getDias(Timestamp dia) throws GestorFormacionExcepcion {
        ArrayList<DiaClase> diaclase = new ArrayList<DiaClase>();
        DiaClase diacla;
        Connection conexion = null;
        try {
            conexion = SQLServerDAOFactory.conecta();
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
        }

        try {
            PreparedStatement stmt = conexion.prepareStatement("SELECT DISTINCT c1.ModId, c1.ClaId, c1.DocId, c1.CurId, c1.ClaFecha, c1.ClaHoraInicioMañ, c1.ClaHoraFinMañ, c1.ClaObserv, c1.ClaHoraInicioTar, c1.ClaHoraFinTar, c1.AulId FROM Clase as c1, Clase as c2 WHERE c1.ClaFecha=? AND c1.ClaFecha=c2.ClaFecha AND (c1.DocId=c2.DocId OR c1.AulId=c2.AulId OR (c1.ClaObserv IS NOT NULL AND c1.ClaObserv!=''))");
            stmt.setTimestamp(1, dia);
            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                diacla = instanciarDiaClase(rs);
                diaclase.add(diacla);
            }
            for (int i = 0; i < diaclase.size() - 1; i++) {
                for (int j = i + 1; j < diaclase.size(); j++) {
                    if (Verificador.comprobarIntervaloHoras(diaclase.get(i).getClaHoraInicioMan(), diaclase.get(i).getClaHoraFinMan(), diaclase.get(j).getClaHoraInicioMan(), diaclase.get(j).getClaHoraFinMan())) {
                        if (diaclase.get(i).getAulId() == diaclase.get(j).getAulId()) {
                            diaclase.get(j).setConflictoAula(true);
                            diaclase.get(i).setConflictoAula(true);
                        }
                        if (diaclase.get(i).getDocId() == diaclase.get(j).getDocId()) {
                            diaclase.get(j).setConflictoDocente(true);
                            diaclase.get(i).setConflictoDocente(true);
                        }
                    }
                    if (Verificador.comprobarIntervaloHoras(diaclase.get(i).getClaHoraInicioTar(), diaclase.get(i).getClaHoraFinTar(), diaclase.get(j).getClaHoraInicioTar(), diaclase.get(j).getClaHoraFinTar())) {
                        if (diaclase.get(i).getAulId() == diaclase.get(j).getAulId()) {
                            diaclase.get(j).setConflictoAula(true);
                            diaclase.get(i).setConflictoAula(true);
                        }
                        if (diaclase.get(i).getDocId() == diaclase.get(j).getDocId()) {
                            diaclase.get(j).setConflictoDocente(true);
                            diaclase.get(i).setConflictoDocente(true);
                        }
                    }
                }
            }
        } catch (SQLException ex) {
            Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
            throw new GestorFormacionExcepcion(rb.getString("no-sql"));
        } finally {
            SQLServerDAOFactory.desconecta(conexion);
        }
        return diaclase;
    }

    /**
     * Método que actualiza las observaciones.
     * @author
     * @param objeto DiaClase.
     */
    private void actualizarObservaciones(DiaClase dia) throws GestorFormacionExcepcion {
        Connection conexion = null;
        PreparedStatement stmt = null;
        if (!dia.getObservacionesActualizadas().equals(dia.getClaObserv())) {
            try {
                conexion = SQLServerDAOFactory.conecta();
            } catch (SQLException ex) {
                Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
                throw new GestorFormacionExcepcion(rb.getString("no-conexion"));
            }
            try {
                stmt = conexion.prepareStatement("UPDATE Clase SET ClaObserv=? WHERE ClaId=?");
                stmt.setString(1, dia.getObservacionesActualizadas());
                stmt.setInt(2, dia.getClaId());
                stmt.executeUpdate();

            } catch (SQLException ex) {
                Logger.getLogger(SQLServerDiaClaseDAO.class.getName()).log(Level.SEVERE, null, ex);
                throw new GestorFormacionExcepcion(rb.getString("no-sql"));
            } finally {
                SQLServerDAOFactory.desconecta(conexion);
            }
        }
    }
}
